#include "httpclient.h"
#include "captchasolver.h"
#include <QUrl>
#include <QBuffer>
#include <QDebug>
#include <QTime>

#undef OFF_DEBUG

HttpClient::HttpClient(QObject *parent) :
    QObject(parent)
{
    socket=new QNetworkAccessManager();
    connect(socket, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(requestFinished(QNetworkReply*)));
    parser=NULL;
    outFile=NULL;
}

void HttpClient::setAddress(Link* link){
    if(parser!=NULL){
        qDebug()<<"Setting adres to already existing http client";
        return;
    }
    this->link=link;
    //host=new QString(link->url().host());
    //qDebug()<<link->url().host();
    parser=SiteParser::getInstance(link->url().host());
    if(parser==NULL){
        errorHandler(Link::ERR_UNKNOWN_PROVIDER);
        return;
    }
    connect(parser, SIGNAL(goForm(QUrl,QString)), this, SLOT(getPage(QUrl,QString)));
    connect(parser, SIGNAL(wait(int)), this, SLOT(waitHandler(int)));
    connect(parser, SIGNAL(error(int)), this, SLOT(errorHandler(int)));
    connect(parser, SIGNAL(info(int)), this, SLOT(infoHandler(int)));

    parser->setLinkAddr(link->url().path());

    socket->setProxy(*(link->proxy()));
    getPage(link->url());
};

void HttpClient::requestFinished(QNetworkReply* rp){

    if(rp->error()!=QNetworkReply::NoError){
        qDebug()<<"Failed to retrive page"<<rp->errorString()<<rp->error();
        return;
    };
    if(QVariant::Invalid!=rply->header(QNetworkRequest::LocationHeader)){
        QUrl url(rply->header(QNetworkRequest::LocationHeader).toUrl());
        //qDebug()<<"URL:"<<rply->header(QNetworkRequest::LocationHeader).toUrl().toString();
        //qDebug()<<"STR:"<<rply->header(QNetworkRequest::LocationHeader).toString();
        getPage(url);
        return;
    }
    //qDebug()<< __FILE__<<":"<<__LINE__<<"\t"<< "request successfully finnished";
    if(outFile!=NULL){
        outFile->close();
        emit finnished(link);
        delete outFile;
    }else{
       parser->testPage();
    }
};


void HttpClient::getPage(QUrl url, QString post){
    QUrl nextHop;
    //qDebug()<<"Last request was: "<<request.url();
    //qDebug()<<"Current url: "<<url;
    if(url.scheme().isEmpty()){
        nextHop.setScheme(request.url().scheme());
    }else{
        nextHop.setScheme(url.scheme());
    };
    if(url.host().isEmpty()){
        nextHop.setHost(request.url().host());
    }else{
        nextHop.setHost(url.host());
    };
    if(url.path().isEmpty()){
        nextHop.setPath(request.url().path());
    }else{
        //czy podmienic tylko plik
        if(url.path().contains("/")){
            nextHop.setPath(url.path());
        }else{
            //take current path, and replace filename
            QString oldPath=request.url().path();
            QStringList pathList=oldPath.split('/');
            pathList.last()=url.path();
            nextHop.setPath(pathList.join("/"));
        }
    };
    if(url.queryItems().isEmpty()){
            nextHop.setQueryItems(request.url().queryItems());
    }else{
        nextHop.setQueryItems(url.queryItems());
    }
    request.setUrl(nextHop);
    //qDebug()<< __FILE__<<":"<<__LINE__<<"\t"<< "Going"<<nextHop.toString()<<"on"<<socket->proxy().port();
    if(!(post.isNull()||post.isEmpty())){
        //header->setContentType("application/x-www-form-urlencoded"); // important
        /*if(request.url().host().contains("filesonic")) {
            QString adres = "http://www.filesonic.com";
            adres.append(post);
            request.setUrl(QUrl(adres));
        }*/

        if(request.url().host()=="")
            request = zapamietaj;
        else
            zapamietaj = request;
        //qDebug()<<"POST"<<post.toAscii();
       // qDebug()<<"REQUEST"<<request.url();
        rply=socket->post(request, post.trimmed().toAscii());
        //rply=socket->post(
    }else{
        //qDebug()<<"GET";
        rply=socket->get(request);
    }
    connect(rply, SIGNAL( readyRead  ( )),
            this, SLOT(responseHeaderReceived ( ) ));
    connect(rply, SIGNAL( error(QNetworkReply::NetworkError)),
            this, SLOT(errorHandler(QNetworkReply::NetworkError)));
}

void HttpClient::responseHeaderReceived ( ){
    if(QVariant::Invalid!=rply->header(QNetworkRequest::LocationHeader)){
        QUrl url(rply->header(QNetworkRequest::LocationHeader).toUrl());
        getPage(url);
        return;
    }

    QString contentTp=rply->header(QNetworkRequest::ContentTypeHeader).toString();
    if(contentTp.contains("html")){
        parser->append(rply->readAll());
    }else if(contentTp.contains("application")){
        //downloading reqiested file
        if(outFile==NULL){
            connect(rply, SIGNAL(downloadProgress(qint64,qint64)),
                    link, SLOT(downloadProgress(qint64,qint64)));
            QString contentDisp(rply->rawHeader("Content-Disposition"));//"attachment; filename="promciad5cpls.part01.rar""
            QRegExp nazwa("filename=\"([^\"]*)");
            QString name(link->fileDownloadName());
            if(nazwa.indexIn(contentDisp, 0)!=-1){
                name=nazwa.cap(1);
            }
            //qDebug()<< __FILE__<<":"<<__LINE__<<"\t"<< "Downloading"<<name<<"on"<<socket->proxy().port();
            outFile=new QFile(name);
            if(outFile->exists()){
                int cnt=0;
                while(!outFile->rename(name+"."+QString().setNum(cnt))){
                    cnt++;
                };
                delete outFile;
                outFile=new QFile(name);
            }
            outFile->open(QFile::WriteOnly);
        }
        outFile->write(rply->readAll());

    }else{
        //qDebug()<< __FILE__<<":"<<__LINE__<<"\t"<< contentTp;
    }
}
HttpClient::~HttpClient(){

}

void HttpClient::errorHandler(QNetworkReply::NetworkError err){
    qDebug()<<"Socket error"<<err;
    errorHandler(Link::ERR_SOCKET_ERROR);
}

void HttpClient::waitHandler(int sec){
    emit wait(sec,link);
}

void HttpClient::errorHandler(int errCode){
    qDebug()<<"Error handler HttpClient"<<errCode;
    emit error(errCode, link);
}

void HttpClient::infoHandler(int errCode){
    qDebug()<<"Info:"<<errCode;
    link->setState(errCode);
}
